package com.sky.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.StatusConstant;
import com.sky.dto.DishDTO;
import com.sky.dto.DishPageQueryDTO;
import com.sky.entity.Dish;
import com.sky.entity.DishFlavor;
import com.sky.entity.Setmeal;
import com.sky.exception.DeletionNotAllowedException;
import com.sky.mapper.DishFlavorMapper;
import com.sky.mapper.DishMapper;
import com.sky.mapper.SetmealDishMapper;
import com.sky.mapper.SetmealMapper;
import com.sky.result.PageResult;
import com.sky.service.DishService;
import com.sky.vo.DishVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Service
public class DishServiceImpl implements DishService {

    @Autowired
    private DishMapper dishMapper;

    @Autowired
    private DishFlavorMapper dishFlavorMapper;

    @Autowired
    private SetmealDishMapper setmealDishMapper;

    @Autowired
    private SetmealMapper setmealMapper;

    @Override
    @Transactional //涉及多张表的操作 需要加事务控制
    public void saveWithFlavor(DishDTO dishDTO) {
        //dishDTO中有菜品基本信息 以及 菜品口味信息
        //1.将菜品基本信息添加到菜品表中
        Dish dish=new Dish();
        BeanUtils.copyProperties(dishDTO,dish);
        dishMapper.insert(dish);//这个sql要完成主键回显
        //将添加后的主键值回显到dish对象中
        Long dishId=dish.getId();

        //2.将相关连的口味信息添加到菜品风味表中
        List<DishFlavor> flavors = dishDTO.getFlavors();
        if (flavors==null || flavors.size()==0) {
            //说明没有菜品口味信息，不进行添加
            return;
        }
        //将每个口味信息都添加上菜品id
        for (DishFlavor dishFlavor:flavors) {
            dishFlavor.setDishId(dishId);
        }
        dishFlavorMapper.insertBatch(flavors);

    }


    /**
     *  菜品分页查询
     * @param dishPageQueryDTO  两个分页条件  三个查询条件
     * @return
     */
    @Override
    public PageResult pageQuery(DishPageQueryDTO dishPageQueryDTO) {
        //1:开启分页操作
        PageHelper.startPage(dishPageQueryDTO.getPage(),dishPageQueryDTO.getPageSize());
        //2:完成处理 条件查询 DishVO 存储 多表查询的结果
        Page<DishVO> page = dishMapper.pageQuery(dishPageQueryDTO);
        //3:解析page
        Long total = page.getTotal();
        List<DishVO> records = page.getResult();
        return new PageResult(total,records);
    }

    @Override
    @Transactional //涉及多张表的操作 需要加事务控制
    public void deleteBatch(List<Long> ids) {
        //1.如果在在售状态不可删除
        for(Long id :ids) {
            Dish dish = dishMapper.getById(id);//根据id查询菜品信息
            Integer status = dish.getStatus();
            if(status== StatusConstant.ENABLE){//是起售 启售  不能删除
                throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);
            }
        }

        //2.如果与套菜关联也不可删除
        // 需要我们去完成中间表 mapper接口的创建
        List<Long>  setmaelIds = setmealDishMapper.getSetmealIdsByDishIds(ids);
        //select setmeal_id from setmeal_dish where dish_id in(17,18,19);
        if(setmaelIds!=null && setmaelIds.size()>0){//有关联
            throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);
        }

        //3.删除的话，要把相关口味表数据删除
        for (Long id : ids) {
            dishMapper.delete(id);//根据菜品id删除菜品数据
            Long dishId = id;
            dishFlavorMapper.deleteByDishId(dishId);//根据菜品id 删除 指定口味信息
        }
    }

    /**
     * 根据菜品id查询 菜品基本信息 查询菜品关联的口味列表
     * @param id
     * @return
     */
    @Override
    public DishVO getByIdWithFlavors(Long id) {
        //1:查询菜品基本数据
        Dish dish = dishMapper.getById(id);
        //2: 查询菜品关联的口味列表
        Long dishId = id;
        List<DishFlavor> flavors = dishFlavorMapper.getByDishId(dishId);
        //3:合二为一
        DishVO dishVO = new DishVO();
        //基本菜品数据添加进来
        BeanUtils.copyProperties(dish,dishVO);
        //口味列表添加进来
        dishVO.setFlavors(flavors);

        return dishVO;
    }

    @Override
    @Transactional//事务控制
    public void updateWithFlavor(DishDTO dishDTO) {
        //1:根据菜品id修改菜品基本信息
        Dish dish = new Dish();//封装修改的信息
        BeanUtils.copyProperties(dishDTO,dish);
        //更新时间 更新人 因为做了自动填充
        dishMapper.update(dish);

        Long dishId = dish.getId();
        //2.1: 根据菜品id 删除之前关联的口味
        dishFlavorMapper.deleteByDishId(dishId);//根据菜品id 删除 指定口味信息
        //2.2: 根据菜品id 添加最新关联的口味
        List<DishFlavor> flavors = dishDTO.getFlavors();
        //遍历集合和数组之前要做非空判断
        if(flavors==null || flavors.size()==0){
            return;//因为没有口味 不需要往口味表添加
        }
        for (DishFlavor flavor : flavors) {
            flavor.setDishId(dishId);
        }
        //循环做完 每个口味信息都有了 菜品id
        // 调用口味mapper 进行批量添加
        dishFlavorMapper.insertBatch(flavors);

    }

    @Override
    @Transactional
    public void startOrStop(Integer status, Long id) {
        Dish dish = new Dish();
        dish.setId(id);
        dish.setStatus(status);
        dishMapper.update(dish);

        //菜品停售时，包含菜品的套餐也要停售
        if(status==StatusConstant.DISABLE) {
            //现根据菜品id查询出关联的套餐id
            //由于这个才参数需要时一个集合，所有要将这个参数放到集合中
            List<Long> ids = new ArrayList<>();
            ids.add(id);
            List<Long> setmealIdsByDishIds = setmealDishMapper.getSetmealIdsByDishIds(ids);
            //看有没有关联过套餐
            if(setmealIdsByDishIds!=null && setmealIdsByDishIds.size()>0) {
                //停售套餐，要一个个的停售
                for (Long setmealIdsByDishId : setmealIdsByDishIds) {
                    //修改setmeal表
                    Setmeal setmeal=new Setmeal();
                    setmeal.setStatus(StatusConstant.DISABLE);
                    setmeal.setId(setmealIdsByDishId);
                    setmealMapper.update(setmeal);
                }
            }
        }



    }

    @Override
    public List<Dish> list(Long categoryId) {
        //查询 select * from dish where categoryId=? and status=?
        //创建一个dish对象来封装查询的条件信息
        Dish queryDish = new Dish();
        queryDish.setCategoryId(categoryId);
        queryDish.setStatus(StatusConstant.ENABLE);

        return dishMapper.list(queryDish);
    }
}